﻿using Adnc.Application.Shared.Dtos;
using Adnc.Application.Shared.Services;
using Adnc.Infra.Helper;
using Adnc.Infra.IRepositories;
using Adnc.Shared.RpcServices.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using WYT.Sys.Application.Contracts.Dtos.RedNews;
using WYT.Sys.Application.Contracts.Services;
using WYT.Sys.Repository.Entities;

namespace WYT.Sys.Application.Services
{
    /// <summary>
    /// 小红书服务
    /// </summary>
    public class RedNewsAppService : AbstractAppService, IRedNewsAppService
    {
        private readonly IEfRepository<RedNewsGroup> _redNewsGroupEfRepository;

        private readonly IEfRepository<RedNewsUserShared> _redNewsUserSharedEfRepository;

        private readonly IEfRepository<RedNews> _redNewsEfRepository;

        private readonly IEfRepository<RedNewsUseComments> _redNewsUseCommentsEfRepository;

        private readonly IEfRepository<RedNewsUserFavorite> _redNewsUserFavoriteEfRepository;

        private readonly IEfRepository<RedNewsUserPraise> _redNewsUserPraiseEfRepository;

        private readonly IUserRpcService _userRpcService;

        public RedNewsAppService(IEfRepository<RedNewsGroup> redNewsGroupEfRepository
            , IEfRepository<RedNews> redNewsEfRepository
            , IEfRepository<RedNewsUserShared> redNewsUserSharedEfRepository
            , IEfRepository<RedNewsUseComments> redNewsUseCommentsEfRepository
            , IEfRepository<RedNewsUserFavorite> redNewsUserFavoriteEfRepository
            , IEfRepository<RedNewsUserPraise> redNewsUserPraiseEfRepository
            , IUserRpcService userRpcService)
        {
            _redNewsEfRepository = redNewsEfRepository;
            _redNewsGroupEfRepository = redNewsGroupEfRepository;
            _redNewsUseCommentsEfRepository = redNewsUseCommentsEfRepository;
            _redNewsUserFavoriteEfRepository = redNewsUserFavoriteEfRepository;
            _redNewsUserPraiseEfRepository = redNewsUserPraiseEfRepository;
            _redNewsUserSharedEfRepository = redNewsUserSharedEfRepository;
            _userRpcService = userRpcService;
        }

        public async Task<AppSrvResult<List<RedNewsGroupDto>>> GetRedNewsGroup()
        {
            return await _redNewsGroupEfRepository.Where(x => x.Deleted == false)
                .OrderBy(x => x.Sort)
                .Select(x => new RedNewsGroupDto
                {
                    Id = x.Id,
                    Name = x.Name,
                    CreateTime = x.CreateTime,
                    Sort = x.Sort,
                }).ToListAsync();
        }

        /// <summary>
        /// 用户分享
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="redNewsId"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<bool>> SharedAsync(long userId, long redNewsId)
        {
            return (await _redNewsUserSharedEfRepository.InsertAsync(new RedNewsUserShared
            {
                Id = IdGenerater.GetNextId(),
                User = userId,
                ShareDate = DateTime.Now,
                RedNewsID = redNewsId
            })) > 0;
        }

        /// <summary>
        /// 用户收藏
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="redNewsId"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<bool>> FavoriteAsync(long userId, long redNewsId)
        {
            var isexit = await _redNewsUserFavoriteEfRepository.AnyAsync(x => x.User == userId && x.RedNewsId == redNewsId);
            if (isexit)
                return true;
            else
                return (await _redNewsUserFavoriteEfRepository.InsertAsync(new RedNewsUserFavorite
                {
                    Id = IdGenerater.GetNextId(),
                    User = userId,
                    CreateDate = DateTime.Now,
                    RedNewsId = redNewsId
                })) > 0;
        }

        /// <summary>
        /// 获取用户收藏列表
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<PageModelDto<RedNewsListDto>>> GetUserFavorite(long userId, SearchPagedDto input)
        {
            var count = await _redNewsUserFavoriteEfRepository.CountAsync(x => x.User  == userId);
            var favorites = await _redNewsUserFavoriteEfRepository.Where(x => x.User == userId)
                .Skip(input.PageSize * (input.PageIndex - 1))
                .Take(input.PageSize)
                .ToListAsync();
            var data = new List<RedNewsListDto>();
            if (favorites.Any())
            { 
                var ids = favorites.Select(x => x.RedNewsId).ToList();
                var rednews  = await _redNewsEfRepository.Where(x => ids.Contains(x.Id)).ToListAsync();
                var userIds = rednews.Select(x => x.User).ToArray();
                var reponse = await _userRpcService.GetUserNameAndHead(userIds);
                if (!reponse.IsSuccessStatusCode)
                    return Problem(null, "服务异常");
                var userinfor = reponse.Content;

                data = (from f in favorites
                       join r in rednews on f.RedNewsId equals r.Id
                       join u in userinfor on r.User equals u.Id
                       select new RedNewsListDto
                       {
                           Id = f.Id,
                           Title = r.Title,
                           UserName = u.Name,
                           UserHead = u.Head,
                           Url = r.CoverAddress,
                           CreateTime = f.CreateDate
                       }).ToList();
            }

            return new PageModelDto<RedNewsListDto>(input.PageIndex, input.PageSize, data, count);
        }
        /// <summary>
        /// 取消收藏
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<bool>> CancelFavoriteAsync(long userId, long Id)
        {
            var favorite = await _redNewsUserFavoriteEfRepository.FindAsync(x => x.RedNewsId == Id);
            if (favorite == null || favorite.User != userId)
                return Problem(null, "操作失败");
            return  (await _redNewsUserFavoriteEfRepository.DeleteAsync(favorite.Id)) > 0;
        }

        /// <summary>
        /// 用户点赞
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="redNewsId"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<bool>> PraisedAsync(long userId, long redNewsId)
        {
            var isexit = await _redNewsUserPraiseEfRepository.AnyAsync(x => x.User == userId && x.RedNewsId == redNewsId);
            if (isexit)
                return true;
            else
                return (await _redNewsUserPraiseEfRepository.InsertAsync(new RedNewsUserPraise
                {
                    Id = IdGenerater.GetNextId(),
                    CreateDate = DateTime.Now,
                    RedNewsId = redNewsId,
                    User = userId
                })) > 0;
        }

        /// <summary>
        /// 获取小红书
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<PageModelDto<RedNewsListDto>>> GetRedNews(RedNewsSearchPagedDto input)
        {
            PageModelDto<RedNewsListDto> result = new PageModelDto<RedNewsListDto>() { PageIndex = input.PageIndex, PageSize = input.PageSize };
            var expression = ExpressionCreator.New<RedNews>()
                .And(x => x.State == 1)
                .AndIf(!string.IsNullOrEmpty(input.Value), x => x.Title.Contains(input.Value))
                .AndIf(input.GroupId.HasValue,x => x.Group == input.GroupId);

            result.TotalCount = await _redNewsEfRepository.CountAsync(expression);
            var data = await _redNewsEfRepository.Where(expression)
                .Skip(input.PageSize * (input.PageIndex - 1))
                .Take(input.PageSize).ToListAsync();
            var userIds = data.Select(x => x.User).ToArray();
            if (userIds.Any())
            {
                var reponse = await _userRpcService.GetUserNameAndHead(userIds);
                if (!reponse.IsSuccessStatusCode)
                    return Problem(null, "服务异常");
                var userinfor = reponse.Content;

                result.Data = (from r in data
                               join u in userinfor on r.User equals u.Id
                               select new RedNewsListDto
                               {
                                   Id = r.Id,
                                   Title = r.Title,
                                   UserName = u.Name,
                                   UserHead = u.Head,
                                   Url = r.CoverAddress,
                                   CreateTime = r.CreateDate
                               }).ToList();
            }

            return result;
        }

        /// <summary>
        /// 根据Id获取小红书
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="redNewsId"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<RedNewsDetailDto>> GetRedNewsByID(long userId, long redNewsId)
        {
            var rednews = await _redNewsEfRepository.FindAsync(redNewsId);
            if (rednews == null)
                return Problem(HttpStatusCode.NotFound, "参数错误");

            var reponse = await _userRpcService.GetUserNameAndHead(new long[] { rednews.User });
            if (!reponse.IsSuccessStatusCode)
                return Problem(null, "服务异常");
            var userinfor = reponse.Content;

            RedNewsDetailDto result = new RedNewsDetailDto()
            {
                Id = rednews.Id,
                Title = rednews.Title,
                PictureAddress = JsonSerializer.Deserialize<string[]>(rednews.PictureAddress),
                VideoAddress = JsonSerializer.Deserialize<string[]>(rednews.VideoAddress),
                Content = rednews.Content,
                CreateTime = DateTime.Now,
                UserHead = userinfor.FirstOrDefault()?.Head,
                UserName = userinfor.FirstOrDefault()?.Name,
            };

            result.Praise = await _redNewsUserPraiseEfRepository.AnyAsync(x => x.RedNewsId == redNewsId && x.User == userId);
            result.PraisedCount = await _redNewsUserPraiseEfRepository.CountAsync(x => x.RedNewsId == redNewsId);
            result.FavoriteCount = await _redNewsUserFavoriteEfRepository.CountAsync(x => x.RedNewsId ==redNewsId);
            result.Favorite = await _redNewsUserFavoriteEfRepository.AnyAsync(x => x.RedNewsId == redNewsId && x.User == userId);
            return result;
        }

        /// <summary>
        /// 获取评论
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<PageModelDto<RedNewsCommentsListDto>>> GetComments(SearchPagedDto<long> input)
        {
            PageModelDto<RedNewsCommentsListDto> result = new PageModelDto<RedNewsCommentsListDto>()
            {
                PageIndex = input.PageIndex,
                PageSize = input.PageSize,
            };
            result.TotalCount = await _redNewsUseCommentsEfRepository.CountAsync(x => x.RedNewsId == input.Value);
            var data = _redNewsUseCommentsEfRepository
                .Where(x => x.RedNewsId == input.Value)
                .OrderByDescending(x => x.CreateDate)
                .Skip(input.PageSize * (input.PageIndex - 1))
                .Take(input.PageSize).ToList();
            if (data.Count > 0)
            {
                var userIds = data.Select(x => x.User).ToList();
                var reponse = await _userRpcService.GetUserNameAndHead(userIds);
                if (!reponse.IsSuccessStatusCode)
                    return Problem(null, "服务异常");
                var userinfor = reponse.Content;
                result.Data = data.Select(x => new RedNewsCommentsListDto
                {
                    UserName = userinfor.FirstOrDefault(c => c.Id == x.User)?.Name,
                    UserHead = userinfor.FirstOrDefault(c => c.Id == x.User)?.Head,
                    Content = x.Content,
                    CreateDate = x.CreateDate
                }).ToList();
            }

            return result;
        }

        /// <summary>
        /// 添加评论
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<bool>> PublishComments(long userId, RedNewsCommentsAddDto input)
        {
            return (await _redNewsUseCommentsEfRepository.InsertAsync(new RedNewsUseComments
            {
                Id = IdGenerater.GetNextId(),
                Content = input.Comment,
                RedNewsId = input.Id,
                User = userId,
                CreateDate = DateTime.Now,
            })) > 0;
        }

        /// <summary>
        /// 添加小红书
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<bool>> AddRedNews(long userId, RedNewsAddDto input)
        {
            return (await _redNewsEfRepository.InsertAsync(new RedNews
            {
                Id= IdGenerater.GetNextId(),
                CoverAddress = input.PictureAddress[0],
                Group = input.Group,
                State = 0,
                CreateDate= DateTime.Now,
                Content = input.Content,
                User = userId,
                VideoAddress = JsonSerializer.Serialize(input.VideoAddress),
                PictureAddress = JsonSerializer.Serialize(input.PictureAddress),
                Title = input.Title,
            })) > 0;
        }

        /// <summary>
        /// 获取用户自己发表的小红书
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<PageModelDto<RedNewsSimpleDot>>> GetUserRedNews(long userId, SearchPagedDto input)
        {
            var count = await _redNewsEfRepository.CountAsync(x => x.User == userId);
            var data = _redNewsEfRepository.Where(x => x.User == userId)
                .OrderByDescending(x => x.CreateDate)
                .Skip(input.PageSize * (input.PageIndex - 1))
                .Take(input.PageSize)
                .Select(x => new RedNewsSimpleDot { 
                    Id = x.Id,
                    CreateDate = x.CreateDate,
                    State = x.State,
                    CoverAddress = x.CoverAddress,
                    Title = x.Title
                }).ToList();
            return new PageModelDto<RedNewsSimpleDot>(input.PageIndex, input.PageSize, data, count);
        }
    }
}
